/**
 * Hibernate工具类
 * @author   zhangfb
 * @created  2016年5月20日
 * @email    zhangfb@vtobank.com
 */
package com.hyacinth.database.hibernate;


import com.hyacinth.utils.StringUtils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 数据库表生成pojo对象
 */
public class TableToPojoUtil {
	
	private static String[] tables = {"hoyi_account_recal_record"};
	
	private static String creator="wzemin"; //创建者
	private static String tableName; //表名
	private static String tableComment; //表注释
	
	private static String basePackage = "com.aghoo.ifpbiz.modules.manage.entity"; //包名
	
	private static List<PojoField> fields; //表字段
	
	private static String jdbcUrl = "jdbc:mysql://47.93.115.174:3306/tyrcb148";
	private static String userName = "root";
	private static String password = "yinfeng2012";
	
	public static void main(String[] args) {
		for (String table : tables) {
			if(table==null || StringUtils.isBlank(table.trim())){
				continue;
			}
			tableName = table;
			// 校验表名称
			if (checkTableName()) {
				System.out.println("校验表名称失败！");
				return;
			}
			System.out.println(tableComment);
			
			// 获取表字段
			fields = getFields();
			
			generate("pojo");
			generate("mapxml");
		}
		
	}
	
	public static void generate(String type) {
		// 获取文件路径
		String filePath = getFilePath(type);
		System.out.println(filePath);
		// 获取模板配置
		String template = dealTemplate(type);
		//System.out.println(template);
		// 写入文件
		if (!writeFile(filePath, template)) {
			System.out.println("写入文件成功！");
		}
	}
	
	/**
	 * 写入文件
	 * @return
	 */
	private static boolean writeFile(String path, String content) {
		// 校验文件
		File file = new File(path);
		if (file.exists()) {
			System.out.println("文件已存在！");
			return true;
		}
		// 写入文件
		try {
	  		FileWriter fw = new FileWriter(file);
			fw.write(content);
			fw.flush();
			fw.close();
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("写入文件异常！");
			return true;
		}
		return false;
	}
	
	/**
	 * 取得文件路径
	 */
	private static String getFilePath(String type) {
		String filePath = "";
		String basePath = System.getProperty("user.dir").replace("\\", "/") + "/src/";
		String packagePath = basePath + basePackage.replace(".", "/") + "/";
		if ("pojo".equals(type)) {
			filePath = packagePath + getClassName(tableName) + ".java";
		} else if ("mapxml".equals(type)) {
			filePath = packagePath + getClassName(tableName) + ".hbm.xml";
		}
		return filePath;
	}
	
	/**
	 * 模板转换
	 * @param type
	 * @return
	 */
	private static String dealTemplate(String type) {
		String newTemplate = getTemplate(type);
		newTemplate = newTemplate.replace("@{basePackage}", basePackage);
		newTemplate = newTemplate.replace("@{tableName}", tableName);
		newTemplate = newTemplate.replace("@{tableComment}", tableComment);
		newTemplate = newTemplate.replace("@{pojoClass}", getClassName(tableName));
		if ("pojo".equals(type)) {
			newTemplate = newTemplate.replace("@{fieldContent}", getFieldContent(fields));
		} else if ("mapxml".equals(type)) {
			newTemplate = newTemplate.replace("@{fieldContent}", getMapXmlContent(fields));
		}
		
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
		String createDate = sdf.format(new Date());
		newTemplate = newTemplate.replace("@{createDate}", createDate);
		newTemplate = newTemplate.replace("@{creator}", creator);
		return newTemplate;
	}
	
	/**
	 * 获取类名称
	 * @param tableName
	 */
	private static String getClassName(String tableName) {
		String className = "";
		if(tableName.startsWith("hoyi_")) {
			className = tableName.substring(5);
		}
		className = StringUtils.toCamelCase(className);
		return className.substring(0, 1).toUpperCase() + className.substring(1);
	}
	
	
	/**
	 * 获取mapxml内容
	 * @return
	 */
	private static String getMapXmlContent(List<PojoField> fields) {
		StringBuilder sb = new StringBuilder();
		for (PojoField field : fields) {
			sb.append("\r\n\t\t"+field.toXmlString());
		}
		return sb.toString().substring(4);
	}
	
	/**
	 * 获取pojo字域内容
	 * @return
	 */
	private static String getFieldContent(List<PojoField> fields) {
		StringBuilder sb = new StringBuilder();
		for (PojoField field : fields) {
			sb.append("\t"+field+"\r\n");
		}
		sb.append("\r\n");
		// 获取pojo方法
		for (PojoField field : fields) {
			String fName = field.getFieldName();
			String nName = fName.substring(0, 1).toUpperCase()+fName.substring(1);
			// get方法
			sb.append("\tpublic "+field.getFieldType()+" get"+nName+"() {\r\n");
			System.out.println(fName);
			if (field.getFieldType().equals("BigDecimal")) {
				sb.append("\t\treturn "+fName+" == null ? BigDecimal.ZERO : "+fName+";\r\n");
			} else if (field.getFieldType().equals("Integer")) {
				sb.append("\t\treturn "+fName+" == null ? 0 : "+fName+";\r\n");
			} else {
				sb.append("\t\treturn "+fName+";\r\n");
			}
			
			sb.append("\t}\r\n");
			// set方法
			sb.append("\tpublic void set"+nName+"("+field.getFieldType()+" "+fName+") {\r\n");
			sb.append("\t\tthis."+fName+" = "+fName+";\r\n");
			sb.append("\t}\r\n");
		}
		return sb.toString().substring(1);
	}
	
	/**
	 * 获取表字段
	 * @return
	 */
	private static List<PojoField> getFields() {
		List<PojoField> fields = new ArrayList<PojoField>();
		try {
			Statement stmt = getConnect().createStatement();
			ResultSet rs = stmt.executeQuery("SHOW FULL COLUMNS FROM "+tableName);
			while (rs.next()) {
				PojoField field = new PojoField();
				field.setColumnName(rs.getString("FIELD"));
				field.setColumnComment(rs.getString("COMMENT"));
				if ("PRI".equals(rs.getString("KEY"))) {
					field.setPrimaryKey(true);
				}
				field.setFieldName(StringUtils.toCamelCase(field.getColumnName()));
				String columnType = rs.getString("TYPE");
				
				field.setColumnType(columnType);
				fields.add(field);
				
			}
			rs.close();
			stmt.close();
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println("获取模板配置异常！");
		}
		return fields;
	}
	
	/**
	 * 获取模板配置
	 * @return
	 */
	private static String getTemplate(String type) {
		String template = "";
		try {
			Statement stmt = getConnect().createStatement();
			ResultSet rs = stmt.executeQuery("SELECT * FROM hoyi_template");
			while (rs.next()) {
				template = rs.getString(type);
			}
			rs.close();
			stmt.close();
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println("获取模板配置异常！");
		}
		// 如果数据库未配置模板则默认以下模板
		if (StringUtils.isBlank(template)) {
			if ("pojo".equals(type)) {
				template = 	"package @{basePackage};\r\n" + 
							"\r\n" + 
							"import java.math.BigDecimal;\r\n" + 
							"import java.util.Date;\r\n" + 
							"\r\n" + 
							"import com.aghoo.jadp.entity.BaseEntity;\r\n" + 
							"import com.aghoo.jadp.utils.java.ClassDesc;\r\n" + 
							"\r\n" + 
							"/**\r\n" + 
							" * @{tableComment}实体类\r\n" + 
							" * @table    @{tableName}\r\n" + 
							" * @author   @{creator}\r\n" + 
							" * @created  @{createDate}\r\n" + 
							" */\r\n" + 
							"@ClassDesc(desc=\"@{tableComment}\")\r\n" + 
							"public class @{pojoClass} extends BaseEntity<@{pojoClass}> {\r\n" + 
							"	private static final long serialVersionUID = 1L;\r\n" + 
							"	@{fieldContent}\r\n" +
							"}";
			} else if ("mapxml".equals(type)) {
				template = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + 
							"<!DOCTYPE hibernate-mapping PUBLIC \"-//Hibernate/Hibernate Mapping DTD 3.0//EN\"\r\n" + 
							"                                   \"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd\">\r\n" + 
							"<hibernate-mapping>\r\n" + 
							"	<class name=\"@{basePackage}.@{pojoClass}\" table=\"@{tableName}\" optimistic-lock=\"version\">\r\n" + 
							"		@{fieldContent}\r\n" + 
							"	</class>\r\n" + 
							"</hibernate-mapping>";
			}
		}
		return template;
	}
	
	/**
	 * 校验表名称
	 * @return
	 */
	private static boolean checkTableName() {
		boolean exist = true;
		try {
			Statement stmt = getConnect().createStatement();
			ResultSet rs = stmt.executeQuery("SHOW TABLE STATUS LIKE '"+tableName+"'");
			while (rs.next()) {
				exist = false;
				tableComment = rs.getString("COMMENT");
			}
			rs.close();
			stmt.close();
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println("校验表名称异常！");
		}
		return exist;
	}
	
	/**
	 * 创建数据库连接
	 * @return
	 */
	private static Connection getConnect() {
		Connection conn = null;
		try {
			conn = DriverManager.getConnection(jdbcUrl, userName, password);
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println("创建数据库连接异常！");
		}
		return conn;
	}
	
	private static class PojoField {
		
		private String fieldName; // 字域名称
		private String fieldType; // 字域类型
		private String columnName; // 字段名称
		private String colxmlType; // 字段类型
		private String columnLength; // 字段长度
		private String columnComment; // 字段注释
		public String getFieldName() {
			return fieldName;
		}
		public void setFieldName(String fieldName) {
			this.fieldName = fieldName;
		}
		public String getFieldType() {
			return fieldType;
		}
		public String getColumnName() {
			return columnName;
		}
		public void setColumnName(String columnName) {
			this.columnName = columnName;
		}
		public void setColumnType(String columnType) {
			if(columnType.startsWith("varchar")){
				this.fieldType = "String";
				this.colxmlType = "string";
			}else if(columnType.startsWith("decimal")){
				this.fieldType = "BigDecimal";
				this.colxmlType = "big_decimal";
			}else if(columnType.startsWith("int")){
				this.fieldType = "Integer";
				this.colxmlType = "integer";
			}else if(columnType.startsWith("tinyint")){
				this.fieldType = "Integer";
				this.colxmlType = "integer";
			}else if(columnType.equals("date")){
				this.fieldType = "Date";
				this.colxmlType = "timestamp";
			}else if(columnType.equals("datetime")){
				this.fieldType = "Date";
				this.colxmlType = "timestamp";
			}else if(columnType.equals("timestamp")){
				this.fieldType = "Date";
				this.colxmlType = "timestamp";
			}else if(columnType.startsWith("bigint")){
				this.fieldType = "Long";
				this.colxmlType = "long";
			}else if(columnType.equals("double")){
				this.fieldType = "Double";
				this.colxmlType = "double";
			}else if(columnType.equals("char(1)")){
				this.fieldType = "Boolean";
				this.colxmlType = "yes_no";
			}else if(columnType.equals("text")){
				this.fieldType = "String";
				this.colxmlType = "string";
			}else{
				this.fieldType = null;
			}
			System.out.println(columnType+":"+this.fieldType);
			
			// 查找规则公式中括号以内的字符
			Pattern p = Pattern.compile("\\(.*?\\)");
			Matcher m = p.matcher(columnType);
			// 遍历找到的所有括号
			while (m.find()) {
				// 去掉括号
				String param = m.group().replaceAll("\\(", "");
				param = param.replaceAll("\\)", "");
				this.columnLength = param;
			}
		}
		public void setColumnComment(String columnComment) {
			this.columnComment = columnComment;
		}
		public void setPrimaryKey(boolean primaryKey) {
		}
		public String toString() {
			if (fieldName.equals("id")) {
				return "private Long id;";
			} else if (fieldName.equals("version")) {
				return "/**hibernate乐观锁**/\r\n\tprivate Integer version;";
			}
			return "/**"+columnComment+"**/\r\n\tprivate "+fieldType+" "+fieldName+";";
		}
		public String toXmlString() {
			if (fieldName.equals("id")) {
				return "<id name=\"id\" column=\"id\" type=\"java.lang.Long\">\r\n\t\t\t<generator class=\"identity\" />\r\n\t\t</id>";
			} else if (fieldName.equals("version")) {
				return "<version name=\"version\" column=\"version\" type=\"integer\"/>";
			} else {
				if (fieldType.equals("String") && columnLength != null) {
					return "<property name=\""+fieldName+"\" column=\""+columnName+"\" type=\""+colxmlType+"\" length=\""+columnLength+"\" />";
				}
				return "<property name=\""+fieldName+"\" column=\""+columnName+"\" type=\""+colxmlType+"\" />";
			}
		}
	}

}
